home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / CPP / WFC010.ZIP / SRC / LSOCKETS.CPP < prev    next >
C/C++ Source or Header  |  1995-12-07  |  7KB  |  270 lines

  1. #include <wfc.h>
  2. #pragma hdrstop
  3.  
  4. /*
  5. ** Author: Samuel R. Blackburn
  6. ** CI$: 76300,326
  7. ** Internet: sammy@sed.csc.com
  8. **
  9. ** You can use it any way you like as long as you don't try to sell it.
  10. **
  11. ** Any attempt to sell WFC in source code form must have the permission
  12. ** of the original author. You can produce commercial executables with
  13. ** WFC but you can't sell WFC.
  14. **
  15. ** Copyright, 1995, Samuel R. Blackburn
  16. **
  17. ** $Workfile: $
  18. ** $Revision: $
  19. ** $Modtime: $
  20. */
  21.  
  22. #if defined( _DEBUG )
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #define new DEBUG_NEW
  26. #endif
  27.  
  28. CListeningSocket::CListeningSocket()
  29. {
  30.    TRACE( "CListeningSocket::CListeningSocket()\n" );
  31.    m_Initialize();
  32. }
  33.  
  34. CListeningSocket::~CListeningSocket()
  35. {
  36.    TRACE( "Destroying a CListeningSocket object\n" );
  37. }
  38.  
  39. #if defined( _DEBUG )
  40.  
  41. void CListeningSocket::Dump( CDumpContext &dump_context ) const
  42. {
  43.    CSimpleSocket::Dump( dump_context );
  44.    dump_context << "{\n";
  45.    dump_context << "   m_ServerSocketID = " << m_ServerSocketID << "\n";
  46.    dump_context << "   m_NumberOfSimultaneousSocketsToAllow = " << m_NumberOfSimultaneousSocketsToAllow << "\n";
  47.    dump_context << "}\n";
  48. }
  49.  
  50. #endif // _DEBUG
  51.  
  52. void CListeningSocket::m_Initialize( void )
  53. {
  54.    ASSERT_VALID( this );
  55.  
  56.    TRACE( "CListeningSocket::m_Initialize(), Initializing a CListeningSocket class\n" );
  57.  
  58.    /*
  59.    ** Make sure that everything is empty
  60.    */
  61.  
  62.    m_ServerSocketID                     = INVALID_SOCKET;
  63.    m_NumberOfSimultaneousSocketsToAllow = 10;
  64. }
  65.  
  66. BOOL CListeningSocket::Open( void )
  67. {
  68.    ASSERT_VALID( this );
  69.  
  70.    if ( m_ServerSocketID != INVALID_SOCKET )
  71.    {
  72.       TRACE( "CListeningSocket::Open(), server socket already created at line %d of %s\n", __LINE__, __FILE__ );
  73.       return( TRUE );
  74.    }
  75.  
  76.    if ( m_PortNumberInNetworkByteOrder == 0 )
  77.    {
  78.       TRACE( "CListeningSocket::open(), can't server socket without a port number at line %d of %s\n", __LINE__, __FILE__ );
  79.       return( FALSE );
  80.    }
  81.  
  82.    /*
  83.    ** Create the server (or listening) socket thingy
  84.    */
  85.  
  86.    m_ServerSocketID = ::socket( AF_INET, SOCK_STREAM, 0 );
  87.  
  88.    if ( m_ServerSocketID == INVALID_SOCKET )
  89.    {
  90.       TRACE( "CListeningSocket::open(), socket() failed at line %d of %s\n", __LINE__, __FILE__ );
  91.  
  92.       m_ErrorCode = ::WSAGetLastError();
  93.       return( FALSE );
  94.    }
  95.  
  96.    /*
  97.    ** We've got a socket thingy but its useless. It doesn't have an address. Let's give it one.
  98.    ** We do this by bind'ing an address and port number to it.
  99.    */
  100.  
  101.    SOCKADDR_IN socket_address;
  102.  
  103.    socket_address.sin_family      = AF_INET;
  104.    socket_address.sin_port        = m_PortNumberInNetworkByteOrder;
  105.    socket_address.sin_addr.s_addr = ::htonl( INADDR_ANY ); // We'll let anybody connect to us
  106.  
  107.    if ( ::bind( m_ServerSocketID, (LPSOCKADDR) &socket_address, sizeof( socket_address ) ) == SOCKET_ERROR )
  108.    {
  109.       TRACE( "CListeningSocket::open(), bind() failed at line %d of %s\n", __LINE__, __FILE__ );
  110.  
  111.       m_ErrorCode = ::WSAGetLastError();
  112.       return( FALSE );
  113.    }
  114.  
  115.    /*
  116.    ** Now the socket thingy has an address and port number.
  117.    */
  118.  
  119.    /*
  120.    ** Now we make it a listening socket and start listening, program execution halts here
  121.    */
  122.    
  123.    if ( ::listen( m_ServerSocketID, m_NumberOfSimultaneousSocketsToAllow ) == SOCKET_ERROR )
  124.    {
  125.       TRACE( "CListeningSocket::Open(), Can't listen() at line %d of %s\n", __LINE__, __FILE__ );
  126.  
  127.       m_ErrorCode = ::WSAGetLastError();
  128.       return( FALSE );
  129.    }
  130.  
  131.    return( TRUE );
  132. }
  133.  
  134. #pragma warning( disable : 4100 )
  135.  
  136. BOOL CListeningSocket::Open( const char *ChannelName, UINT port_number, CFileException *pError )
  137. {
  138.    ASSERT_VALID( this );
  139.  
  140.    SetPort( (short) port_number );
  141.  
  142.    return( Open() );
  143. }
  144.  
  145. #pragma warning( default : 4100 )
  146.  
  147. BOOL CListeningSocket::WaitForConnection( void )
  148. {
  149.    ASSERT_VALID( this );
  150.  
  151.    if ( m_PortNumberInNetworkByteOrder == 0 )
  152.    {
  153.       return( FALSE );
  154.    }
  155.  
  156.    if ( m_ServerSocketID == INVALID_SOCKET )
  157.    {
  158.       if ( Open() == FALSE )
  159.       {
  160.          TRACE( "CListeningSocket::WaitForConnection(), Can't open() at line %d of %s\n", __LINE__, __FILE__ );
  161.          return( FALSE );
  162.       }
  163.    }
  164.  
  165.    SOCKADDR incoming_socket_address;
  166.  
  167.    int byte_count = 0;
  168.  
  169.    byte_count = sizeof( incoming_socket_address );
  170.  
  171.    ::ZeroMemory( &incoming_socket_address, byte_count );
  172.  
  173.    /*
  174.    ** PROGRAM EXECUTION STOPS HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  175.    **
  176.    ** accept() is a blocking call meaning that the this thread of execution is paused
  177.    ** (ie goes to sleep) until someone on the network connects to us. We will "wake up"
  178.    ** when that happens and continue along our merry way.
  179.    */
  180.  
  181.    m_SocketID = ::accept( m_ServerSocketID, &incoming_socket_address, &byte_count );
  182.  
  183.    if ( m_SocketID == INVALID_SOCKET )
  184.    {
  185.       m_ErrorCode = ::WSAGetLastError();
  186.       return( FALSE );
  187.    }
  188.  
  189.    /*
  190.    ** The method for actually converting the incoming address to something that is human
  191.    ** readable is either undocumented or extremely poorly documented. Not suprising since
  192.    ** the idea of sockets came out of the Unix world...
  193.    */
  194.  
  195.    LPSTR dotted_ip_address = (LPSTR) NULL;
  196.     
  197.    struct in_addr internet_address;
  198.  
  199.    /*
  200.    ** Aren't these structure member names intuitively obvious??
  201.    */
  202.  
  203.    internet_address.S_un.S_un_b.s_b1 = incoming_socket_address.sa_data[ 2 ];
  204.    internet_address.S_un.S_un_b.s_b2 = incoming_socket_address.sa_data[ 3 ];
  205.    internet_address.S_un.S_un_b.s_b3 = incoming_socket_address.sa_data[ 4 ];
  206.    internet_address.S_un.S_un_b.s_b4 = incoming_socket_address.sa_data[ 5 ];
  207.  
  208.    dotted_ip_address = ::inet_ntoa( internet_address );
  209.  
  210.    if ( dotted_ip_address == (LPSTR) NULL )
  211.    {
  212.       m_ErrorCode = WSAEINVAL;
  213.       return( FALSE );
  214.    }
  215.  
  216.    ULONG temp_long = 0L;
  217.  
  218.    temp_long = ::inet_addr( (LPCSTR) dotted_ip_address );
  219.  
  220.    if ( temp_long == INADDR_NONE )
  221.    {
  222.       m_ErrorCode = WSAEINVAL;
  223.       return( FALSE );
  224.    }
  225.  
  226.    LPHOSTENT host_entry_p = (LPHOSTENT) NULL;
  227.  
  228.    host_entry_p = ::gethostbyaddr( (const char *) &temp_long, 4, PF_INET );
  229.  
  230.    if ( host_entry_p == (LPHOSTENT) NULL )
  231.    {
  232.       m_ErrorCode = ::WSAGetLastError();
  233.       return( FALSE );
  234.    }
  235.  
  236.    TRACE( "%s (%s) just connected to us\n", host_entry_p->h_name, (const char *) dotted_ip_address );
  237.  
  238.    SetAddress( dotted_ip_address );
  239.  
  240.    OnNewConnection( m_SocketID, Name, dotted_ip_address );
  241.  
  242.    return( TRUE );
  243. }
  244.  
  245. BOOL CListeningSocket::WaitForConnection( const int port_number )
  246. {
  247.    ASSERT_VALID( this );
  248.    ASSERT( port_number > 0 );
  249.  
  250.    SetPort( (short) port_number );
  251.  
  252.    return( WaitForConnection() );
  253. }
  254.  
  255. BOOL CListeningSocket::WaitForConnection( const char *p_name )
  256. {
  257.    ASSERT_VALID( this );
  258.    ASSERT( p_name != NULL );
  259.  
  260.    if ( p_name == NULL )
  261.    {
  262.       m_ErrorCode = ERROR_INVALID_PARAMETER;
  263.       return( FALSE );
  264.    }
  265.  
  266.    SetPort( p_name );
  267.  
  268.    return( WaitForConnection() );
  269. }
  270.